package com.kjlink.demo.sofa.common.filter;


/**
 * 描述:
 *
 * @author Vic.xu
 * @since 2025-10-24 13:57
 */

import com.alipay.sofa.rpc.context.RpcInternalContext;
import com.alipay.sofa.rpc.core.exception.RpcErrorType;
import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.filter.AutoActive;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalTime;
import java.util.random.RandomGenerator;

/**
 * 统一鉴权 Filter：消费端添加鉴权头，服务端校验
 * <a href="https://www.sofastack.tech/projects/sofa-rpc/custom-filter/">SOFA RPC Filter</a>
 */
@Extension("customer")
@AutoActive(providerSide = true, consumerSide = true)
public class CustomFilter extends Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);

    @Override
    public boolean needToLoad(FilterInvoker invoker) {
        LOGGER.info("load SOFA RPC custom filter");
        return true;
    }

    @Override
    public SofaResponse invoke(FilterInvoker invoker, SofaRequest request) throws SofaRpcException {
        LOGGER.info("into  SOFA RPC custom filter");
        RpcInternalContext context = RpcInternalContext.getContext();
        String requestInfo = requestInfo(request);
        if (context.isConsumerSide()) {

            String token = "token_" + LocalTime.now();
            LOGGER.info("给请求 {} 携带一个token: {}", requestInfo, token);
            request.addRequestProp("token", token);

        } else if (context.isProviderSide()) {
            String token = (String) request.getRequestProp("token");
            LOGGER.info("校验请求 {} 的 token: {}", requestInfo, token);
            if (token == null || !checkToken(token)) {

                /**
                 * 抛出异常，会返回给调用方一个错误码，并返回给调用方一个错误信息    <br />
                 * 形如： com.alipay.sofa.rpc.core.exception.SofaRpcException: Auth filter error   <br />
                 * 需要使用 RpcErrorType ， 自定义错误码 不行
                 */
                throw new SofaRpcException(RpcErrorType.SERVER_FILTER, "Auth filter error");
            }

        }
        return invoker.invoke(request);
    }


    private String requestInfo(SofaRequest request) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(request.getInterfaceName());
        sb.append("#").append(request.getMethodName()).append("(");
        String[] methodArgSigs = request.getMethodArgSigs();
        if (methodArgSigs != null && methodArgSigs.length > 0) {
            sb.append(methodArgSigs[0]);
            for (int i = 1; i < methodArgSigs.length; i++) {
                sb.append(", ").append(methodArgSigs[i]);
            }
        }
        sb.append(")");
//        sb.append("uniqueId: ").append(request.getTargetServiceUniqueName()).append(", ");
        sb.append("]");
        return sb.toString();
    }

    /**
     * 假装在检验token
     */
    private boolean checkToken(String token) {
        boolean b = RandomGenerator.getDefault().nextBoolean();
        if (!b) {
            LOGGER.warn("token: {} 校验失败", token);
        }
        return b;
    }
}